package org.mbcorp.sar.service.impl;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.annotation.Resource;

import org.mbcorp.sar.dao.OperadorDAO;
import org.mbcorp.sar.model.Fase;
import org.mbcorp.sar.model.Horario;
import org.mbcorp.sar.model.Logro;
import org.mbcorp.sar.model.Medalla;
import org.mbcorp.sar.model.Operador;
import org.mbcorp.sar.model.Solicitud;
import org.mbcorp.sar.service.OperadorService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service("operadorService")
public class OperadorServiceImpl implements OperadorService {

	@Autowired
    private MessageSource message;
	
	private static final Logger LOGGER = LoggerFactory
			.getLogger(OperadorServiceImpl.class);

	@Resource
	private OperadorDAO operadorDAO;
	
	

	@Transactional
	@Override
	public Operador grabar(Operador created) {
		LOGGER.debug("Creando nuevo operador con informacion: " + created);

		return operadorDAO.save(created);
	}

	@Override
	public Operador eliminar(Integer operadorId)
			throws RuntimeException {
		LOGGER.debug("Eliminando operador con id: " +  operadorId);

		Operador eliminado =  operadorDAO.findOne(operadorId);

		if (eliminado == null) {
			LOGGER.debug("No se encontro operador con id: " + operadorId);
			throw new RuntimeException();
		}

		operadorDAO.delete(eliminado);
		return eliminado;
	}

	@Transactional(readOnly = true)
	@Override
	public List<Operador> buscarTodos() {
		LOGGER.debug("Buscando todos las operadors");
		return operadorDAO.findAll();
	}

	@Transactional(readOnly = true)
	@Override
	public Operador buscarPorId(Integer id) {
		LOGGER.debug("Buscando operador con id: " + id);
		return operadorDAO.findOne(id);
	}

	@Transactional
	@Override
	public Operador actualizar(Operador actualizado)
			throws RuntimeException {
		LOGGER.debug("Actualizando operador con informacion: " + actualizado);

		Operador operador = operadorDAO.findOne(actualizado.getId());

		if (operador == null) {
			LOGGER.debug("No se encontro operador con id: "
					+ actualizado.getId());
			throw new RuntimeException();
		}

		return operador;
	}

	@Override
	public List<Operador> buscarPorLogin(String login) {		
		return operadorDAO.buscarPorLogin(login);
	}

	@Override
	public List<Operador> buscarDisponibles(Integer idFase) {
		List<Operador> disponibles = operadorDAO.buscarRecursosDisponibles(idFase);
		for(Operador o : disponibles){
			this.calcularFechaDisponibilidad(o);
		}
		return disponibles;		
	}
	
	private void calcularFechaDisponibilidad(Operador operador){
		Calendar fechaD = Calendar.getInstance();
		fechaD.set(Calendar.MINUTE, 0);
		fechaD.set(Calendar.SECOND, 0);		
		if(fechaD.get(Calendar.HOUR_OF_DAY) < operador.getJornadaInicio()){
			fechaD.set(Calendar.HOUR_OF_DAY, operador.getJornadaInicio());
        }
        if(fechaD.get(Calendar.HOUR_OF_DAY) >= operador.getJornadaFinProvisional()){
        	fechaD.set(Calendar.HOUR_OF_DAY, operador.getJornadaInicio());
        	fechaD.add(Calendar.DAY_OF_MONTH, 1);
        }
		for(Horario h : operador.getHorarios()){
			Calendar inicio = Calendar.getInstance();
			inicio.setTime(h.getFechaInicio());
			Calendar fin = Calendar.getInstance();
			fin.setTime(h.getFechaFin());
			if((fechaD.after(inicio) || fechaD.equals(inicio)) && fechaD.before(fin)){
				fechaD = fin;
			}
		}
		operador.setFechaDisponibilidad(fechaD.getTime());
	}
	
	public List<Operador> filtrarOperadores(Solicitud solicitud){
		Set<Operador> o = new HashSet<Operador>();
		for(Fase f : solicitud.getFases()){
			for(Horario h : f.getHorarios()){
				o.add(h.getOperador());
			}
		}
		List<Operador> operadores = new ArrayList<Operador>();
		operadores.addAll(o);
		return operadores;
		
	}
	
	public List<Operador> filtrarOperadores(Fase fase){
		Set<Operador> o = new HashSet<Operador>();
		for(Horario h : fase.getHorarios()){
			o.add(h.getOperador());
		}
		List<Operador> operadores = new ArrayList<Operador>();
		operadores.addAll(o);
		return operadores;
		
	}
	
	@Transactional(readOnly = true)
	public List<Operador> buscarTodosPorPuntos(){
		return operadorDAO.findAll(sortByPuntajeAcumuladoDesc());
	}
	
	private Sort sortByPuntajeAcumuladoDesc() {
        return new Sort(Sort.Direction.DESC, "puntajeAcumulado");
    }
	
	//provisional
//	public Operador agregarMedallasObtenidas(Operador o, List<Medalla> medallas){
//		List<Medalla> medallasObtenidas = new ArrayList<Medalla>();
//		for(Medalla m : medallas){
//			m.setTieneMedalla(false);
//			m.setProgresoOperador(0);
//			for(Logro l : o.getLogros()){
//				if(l.getMedalla().getId() == m.getId()){
//					if(l.getFechaObtencion() != null){
//						m.setTieneMedalla(true);						
//					}
//					m.setProgresoOperador(l.getNivelProgreso());
//					break;
//				}
//			}
//			medallasObtenidas.add(m);
//		}
//		o.setListaMedallasObtenidas(medallasObtenidas);
//		return o;
//	}

}

